package openase.audiosearch.client.registration.controller;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

import openase.audio.AudioUtils;
import openase.audio.conversion.AudioConversionException;
import openase.audio.conversion.AudioConversionUtils;
import openase.audiosearch.client.ClientProperties;
import openase.audiosearch.comm.CommUtil;
import openase.audiosearch.comm.request.AudioRegistration;
import openase.audiosearch.comm.request.encoder.facade.RequestEncoderFacade;
import openase.audiosearch.comm.response.ExecutionError;
import openase.audiosearch.comm.response.RegistrationSuccessful;
import openase.audiosearch.comm.response.Response;
import openase.audiosearch.comm.response.UnknownRequest;
import openase.audiosearch.comm.response.decoder.facade.ResponseDecoderFacade;

import org.apache.commons.io.IOUtils;

public class AudioRegistrationController {

	public byte[] getAudio(String filepath) {
		File file = new File(filepath);
		if (!file.exists()) {
			throw new IllegalArgumentException("File not found: \"" + filepath + "\"");
		}

		try {
			return AudioConversionUtils.readFile(file, AudioUtils.getRecordingFormat());
		} catch (AudioConversionException e) {
			throw new RuntimeException("E" + e.getMessage(), e);
		}
	}

	public void register(String name, byte[] audio) {
		SocketChannel channel = null;
		try {
			try {
				channel = CommUtil.connect(ClientProperties.getServerIP(), ClientProperties.getServerPort());
			} catch (IOException e) {
				throw new RuntimeException("Error connecting to the server.", e);
			}

			AudioRegistration registration = new AudioRegistration(name, audio);

			ByteBuffer requestBuffer = RequestEncoderFacade.encode(registration);
			try {
				CommUtil.send(channel, requestBuffer);
			} catch (IOException e) {
				throw new RuntimeException("Error sending request to the server.", e);
			}

			ByteBuffer responseBuffer;
			try {
				responseBuffer = CommUtil.recv(channel);
			} catch (IOException e) {
				throw new RuntimeException("Error receiving response from the server.", e);
			}
			Response response = ResponseDecoderFacade.decode(responseBuffer);

			if (response instanceof ExecutionError) {
				throw new RuntimeException("An error occurred in the server while registering the audio: " + ((ExecutionError) response).getErrorMessage());
			}
			if (response instanceof UnknownRequest) {
				throw new RuntimeException("The server did not recognize the request");
			}
			if (response instanceof RegistrationSuccessful) {
				// ok
				return;
			}
			// an unknown response has been received
			throw new RuntimeException("The response from the server could not be recognized: " + response);
		} finally {
			IOUtils.closeQuietly(channel);
		}
	}

}
